﻿using HK.Core.Common.Protocol;
using HK.Core.Common.Protocol.Data;
using HK.Core.Counter.Protocol;
using HK.Core.Load.Protocol.Signal;
using HK.Core.Pool.Protocol;

namespace HK.Core.Load.Protocol.Data
{

    /// <summary>
    /// 加载资产类型
    /// </summary>
    public enum LoadAssetType
    {
        /// <summary>
        /// 未知
        /// </summary>
        UnKnown,
        
        /// <summary>
        /// 实体
        /// </summary>
        Entity,
        
        /// <summary>
        /// 资产
        /// </summary>
        Asset,
        
        /// <summary>
        /// 场景
        /// </summary>
        Scene,
        
        /// <summary>
        /// Ab
        /// </summary>
        AssetBundle
    }
    
    /// <summary>
    /// 接在选项
    /// </summary>
    public enum LoadOptions
    {
        /// <summary>
        /// 延迟释放
        /// <para>* 既:倒计时释放</para>
        /// </summary>
        Delay = 0x00000001,
        /// <summary>
        /// 自动释放
        /// <para>* 既:引用计数释放</para>
        /// </summary>
        Auto = 0x00000002,
        /// <summary>
        /// 立即释放
        /// </summary>
        ReleaseImmediately = 0x00000004,
        /// <summary>
        /// 永生
        /// </summary>
        Immortal = 0x00000008
    }
    
    /// <summary>
    /// 加载方式
    /// </summary>
    public enum LoadFrom
    { 
        Unknown,
        Resource,
        AssetBundle,
        ResourceAtlas,
        AssetBundleAtlas
    }
    
    /// <summary>
    /// 接口 : 加载资产基类
    /// </summary>
    public interface IAssetBase : IJsonData, IPoolElement
    {
        
        /// <summary>
        /// Key
        /// </summary>
        string Key { get; }
        
        /// <summary>
        /// 加载资产类型
        /// </summary>
        LoadAssetType LoadType { get; }
        
        /// <summary>
        /// 异步标志位
        /// <para>* true : 异步加载</para>
        /// <para>* false : 同步加载</para>
        /// </summary>
        bool Async { get; }
        
        /// <summary>
        /// 设定信息
        /// </summary>
        /// <param name="iKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        void SetInfo(string iKey, int iOptions, bool iAsync = false, float iCoolTime = 30.0f);
        
#region Options
        
        /// <summary>
        /// 加载选项
        /// </summary>
        int Options { get; }
        
        /// <summary>
        /// 永生
        /// </summary>
        bool Immortal { get; }
        /// <summary>
        /// 自动释放
        /// <para>* 既:引用计数释放</para>
        /// </summary>
        bool Auto { get; }
        /// <summary>
        /// 延迟释放
        /// <para>* 既:倒计时释放</para>
        /// </summary>
        bool Delay { get; }
        
        /// <summary>
        /// 立即释放
        /// </summary>
        bool ReleaseImmediately { get; }

        /// <summary>
        /// 升级加载选项
        /// </summary>
        /// <param name="iOptions">加载选项</param>
        void UpgradeLoadOptions(int iOptions);

#endregion

#region LoadFrom

        /// <summary>
        /// 加载源头
        /// </summary>
        LoadFrom From { get; }
        
        /// <summary>
        /// 从Resources中加载的资源
        /// </summary>
        bool FromResource { get; }
        
        /// <summary>
        /// 从Ab加载的资源
        /// </summary>
        bool FromAb { get; }
        
        /// <summary>
        /// 从Resources中的图集加载
        /// </summary>
        bool FromResourceAtlas { get; }
        
        /// <summary>
        /// 从Ab中的图集加载
        /// </summary>
        bool FromAbAtlas { get; }
        
        /// <summary>
        /// 从图集加载
        /// </summary>
        bool FromAtlas { get; }

#endregion

#region Caller

        /// <summary>
        /// 调用者
        /// </summary>
        string Caller { get; }

        /// <summary>
        /// 更新调用者
        /// </summary>
        /// <param name="iCaller"></param>
        void UpdateCaller(string iCaller);
        
#endregion

#region Use&UnUse

        /// <summary>
        /// 引用计数
        /// <para>* 当引用计数小于等于0时, 会触发自动释放。</para>
        /// </summary>
        int ReferenceCount { get; }

        /// <summary>
        /// 使用
        /// <para>* 每使用一次，该引用计数会自增一</para>
        /// </summary>
        void Use();

        /// <summary>
        /// 撤销使用
        /// <para>* 每撤销一次，该引用计数会自减一, 当引用计数小于等于0时，会自动释放或者触发倒计时释放</para>
        /// </summary>
        /// <param name="iForce">强制标志位(会强制将引用计数清零，后强制释放)</param>
        void UnUse(bool iForce = false);

#endregion

#region Delay

        /// <summary>
        /// 倒计时计数器
        /// </summary>
        ITimeCounter CountDown { get; }
        
        /// <summary>
        /// 倒计时中
        /// </summary>
        bool IsCounting { get; }

        /// <summary>
        /// 冷却时间
        /// <para>* 单位 : 秒</para>
        /// <para>* 当冷却时间小于等于0秒时，会触发自动释放。</para>
        /// </summary>
        float CoolTime { get; }

        /// <summary>
        /// 更新时间
        /// </summary>
        /// <param name="iDeltaTime">变化时间</param>
        void UpdateTime(float iDeltaTime);

        /// <summary>
        /// 重置释放倒计时
        /// </summary>
        void RestartTimeCounter();

        /// <summary>
        /// 重置释放倒计时
        /// </summary>
        void ResetTimeCounter();

        /// <summary>
        /// 停止加载时间倒计时
        /// </summary>
        void StopTimeCounter();

#endregion
        
    }
}
